#include "LightSystem.hpp"
#include "OpenGL.hpp"

using namespace Typhoon;

LightSystem::LightSystem()
{
	AddComponent<Transform>();
	AddComponent<Light>();
	
}

LightSystem::~LightSystem()
{
}


void LightSystem::GameObjectAdded( GameObject* gameObject )
{
	Light* light = gameObject->GetComponent<Light>();
	Visualizer* visualizer = new Visualizer();
	
	AddData(light, visualizer);
	Transform* transform = gameObject->GetComponent<Transform>();
	transform->World.HasBecomeDirty += event_handler(this, &LightSystem::TransformChanged);
	transform->World.MakeDirty();
}


void LightSystem::GameObjectRemoved( GameObject* gameObject )
{
	Light* light = gameObject->GetComponent<Light>();

	Visualizer* visualizer = (Visualizer*)GetData(light);
	delete visualizer;

	gameObject->GetComponent<Transform>()->World.HasBecomeDirty -= event_handler(this, &LightSystem::TransformChanged);
}

void LightSystem::TransformChanged(DirtyProperty<Transform*, Matrix4x4>* dirtyProperty) {
	insertionChecks.insert(dirtyProperty->GetOwner());
}

void LightSystem::CheckVisiblity( Transform* transform )
{
	/*
	Light* meshVisualizer = transform->gameObject->GetComponent<Light>();
    Visualizer* visualizer = (Visualizer*)GetData(meshVisualizer);
	bool isVisible = viewport.Intersect(visualizer->BoundingBox);
	
	if (isVisible) {
		visibleObjects.push_back(meshVisualizer);
		//sortVisibleObjects = true;
	}

	return;
	*/
	
}


void LightSystem::GridInsertion(Transform* transform) {
	/*
	T* renderable = transform->gameObject->GetComponent<T>();

	Mesh* mesh = renderable->Mesh;
	if (!mesh) return;

	const Matrix3x3& t = transform->Transform.GetValue();

	Box boundingBox = mesh->BoundingBox;

	boundingBox.FromMatrix(t);

	Visualizer* visualizer = (Visualizer*)GetData(meshVisualizer);

	grid.Remove(transform, visualizer->BoundingBox);
	grid.Add(transform, boundingBox);
	visualizer->BoundingBox = boundingBox;
	*/
}


void LightSystem::Render(GameObject* camera, const Box& viewport) {

	this->camera = camera;
	this->viewport = viewport;

	

	/*
	if (!insertionChecks.empty()) {
		for (InsertionChecks::iterator it=insertionChecks.begin(); it!=insertionChecks.end(); ++it) {
			GridInsertion(*it);
		}
		insertionChecks.clear();
	}


	visibleObjects.clear();
	int counter = 0;
	grid.StartIteration(this->viewport);
	Transform* transform;
	while(grid.GetNext(transform)) {
		CheckVisiblity(transform);
		counter++;
	}
	*/
	

	visibleLights.clear();
	GameObjects& objs = GetGameObjects();
	for	(GameObjects::iterator it = objs.begin(); it!=objs.end(); ++it) {
		visibleLights.push_back((*it)->GetComponent<Light>());
	}
	
	for (int i=0; i<MaxLights; i++) {
		glDisable(GL_LIGHT0 + i);
	}

	int j=visibleLights.size();
	for (int i=0; i<j; i++) {

		Light* light = visibleLights[i];

		glEnable(GL_LIGHT0 + i);

		Transform* transform = light->gameObject->GetComponent<Transform>();

		Vector3 position = transform->World.GetValue()->TransformPosition(0);
		
		float pos[] = { position.x, position.y, position.z, 1.0f }; //last param 0==Directional 

		glLightfv(GL_LIGHT0+i, GL_POSITION, pos);

		GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0};
		glLightfv(GL_LIGHT0 + i, GL_AMBIENT, light_ambient);

		//RenderLight(visibleLights[i]);
	}

	if (j>0) {
		glEnable(GL_LIGHTING);
	} else {
		glDisable(GL_LIGHTING);
	}

}


void LightSystem::RenderLight( Light* light )
{
	
}
